<!DOCTYPE HTML>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
		<title>SlickGrid example: Frozen Columns and Rows</title>
		<link rel="stylesheet" href="../slick.grid.css" type="text/css" media="screen" charset="utf-8" />
		<link rel="stylesheet" href="../controls/slick.pager.css" type="text/css" media="screen" charset="utf-8" />
        <link rel="stylesheet" href="../css/smoothness/jquery-ui-1.8.24.custom.css" type="text/css" media="screen" charset="utf-8" />
		<link rel="stylesheet" href="examples.css" type="text/css" media="screen" charset="utf-8" />
		<link rel="stylesheet" href="../controls/slick.columnpicker.css" type="text/css" media="screen" charset="utf-8" />
		<style>
		.cell-title {
			font-weight: bold;
		}

		.cell-effort-driven {
			text-align: center;
		}

        .cell-selection {
            border-right-color: silver;
            border-right-style: solid;
            background: #f5f5f5;
            color: gray;
            text-align: right;
            font-size: 10px;
        }

        .slick-row.selected .cell-selection {
            background-color: transparent; /* show default selected row background */
        }

		.slick-headerrow-column {
			background: #87ceeb;
			text-overflow: clip;
			-moz-box-sizing: border-box;
			box-sizing: border-box;
		}

		.slick-headerrow-column input {
			margin: 0;
			padding: 0;
			width: 100%;
			height: 100%;
			-moz-box-sizing: border-box;
			box-sizing: border-box;
		}
	</style>
	</head>
	<body>
		<div style="position:relative">
			<div style="width:600px;">
				<div class="grid-header" style="width:100%">
					<label>SlickGrid</label>
					<span style="float:right" class="ui-icon ui-icon-search" title="Toggle search panel" onclick="toggleFilterRow()"></span>
				</div>
				<div id="myGrid" style="width:100%;height:350px;"></div>
				<div id="pager" style="width:100%;height:20px;"></div>
			</div>

			<div class="options-panel">
				<b>Search:</b>
				<hr/>
				<div style="padding:6px;">
					<label style="width:200px;float:left">Frozen Row:</label>
					<input type=text id="frozenRow" style="width:100px;" value=5>
					<button id="setFrozenRow">Set</button>
					<br/><br/>
					<label style="width:200px;float:left">Frozen Column:</label>
					<input type=text id="frozenColumn" style="width:100px;" value=2>
					<button id="setFrozenColumn">Set</button>
					<br/><br/>
					<button id="btnSelectRows">Select first 10 rows</button>

					<br/>
					<h2>Demonstrates:</h2>
					<ul>
						<li>a filtered Model (DataView) as a data source instead of a simple array</li>
						<li>grid reacting to model events (onRowCountChanged, onRowsChanged)</li>
						<li>
							<b>FAST</b> DataView recalculation and <b>real-time</b> grid updating in response to data changes.<br/>
							The grid holds <b>50'000</b> rows, yet you are able to sort, filter, scroll, navigate and edit as if it had 50 rows.
						</li>
						<li>adding new rows, bidirectional sorting</li>
						<li>column options:  cannotTriggerInsert</li>
						<li>events: onCellChange, onAddNewRow, onKeyDown, onSelectedRowsChanged, onSort</li>
						<li><font color=red>NOTE:</font>  all filters are immediately applied to new/edited rows</li>
						<li>Handling row selection against model changes.</li>
						<li>Paging.</li>
						<li>inline filter panel</li>
					</ul>
				</div>
			</div>
		</div>

        <div id="inlineFilterPanelL" style="display:none;background:#dddddd;padding:3px;color:black;">
            Show tasks with title including <input type="text" id="txtSearch2">
        </div>

		<div id="inlineFilterPanelR" style="display:none;background:#dddddd;padding:6px;color:black;">
			and % at least &nbsp; <div style="width:100px;display:inline-block;" id="pcSlider2"></div>
		</div>

		<script language="JavaScript" src="../lib/firebugx.js"></script>

		<script src="../lib/jquery-1.7.min.js"></script>
		<script language="JavaScript" src="../lib/jquery-ui-1.8.24.custom.min.js"></script>
		<script src="../lib/jquery.event.drag-2.2.js"></script>
		<script src="../lib/jquery.mousewheel.js"></script>

		<script src="../slick.core.js"></script>
		<script src="../slick.editors.js"></script>
		<script src="../slick.formatters.js"></script>
		<script src="../plugins/slick.rowselectionmodel.js"></script>
		<script src="../slick.grid.js"></script>
		<script src="../slick.dataview.js"></script>
		<script src="../controls/slick.pager.js"></script>
		<script src="../controls/slick.columnpicker.js"></script>

		<script>
		$(function() {
		$('#frozenColumn').val(options.frozenColumn);
	});


	var dataView;
	var grid;
	var data = [];

	var columns = [{
		id: "sel",
		name: "#",
		field: "num",
		behavior: "select",
		cssClass: "cell-selection",
		width: 40,
		cannotTriggerInsert: true,
		resizable: false,
		unselectable: true
	}, {
		id: "title",
		name: "Title",
		field: "title",
		cssClass: "cell-title",
		editor: Slick.Editors.Text,
		validator: requiredFieldValidator,
		sortable: true
	}, {
		id: "duration",
		name: "Duration",
		field: "duration",
		editor: Slick.Editors.Text,
		sortable: true
	}, {
		id: "%",
		name: "% Complete",
		field: "percentComplete",
		resizable: false,
		width: 80,
		formatter: Slick.Formatters.PercentComplete,
		editor: Slick.Editors.PercentComplete,
		sortable: true
	}, {
		id: "start",
		name: "Start",
		field: "start",
		editor: Slick.Editors.Date,
		sortable: true
	}, {
		id: "finish",
		name: "Finish",
		field: "finish",
		editor: Slick.Editors.Date,
		sortable: true
	}, {
		id: "effort-driven",
		name: "Effort Driven",
		cssClass: "cell-effort-driven",
		field: "effortDriven",
		formatter: Slick.Formatters.Checkmark,
		editor: Slick.Editors.Checkbox,
		cannotTriggerInsert: true,
		sortable: true
	}, {
		id: "title1",
		name: "Title1",
		field: "title1",
		cssClass: "cell-title",
		editor: Slick.Editors.Text,
		validator: requiredFieldValidator,
		sortable: true
	}, {
		id: "title2",
		name: "Title2",
		field: "title2",
		cssClass: "cell-title",
		editor: Slick.Editors.Text,
		validator: requiredFieldValidator,
		sortable: true
	}, {
		id: "title3",
		name: "Title3",
		field: "title3",
		cssClass: "cell-title",
		editor: Slick.Editors.Text,
		validator: requiredFieldValidator,
		sortable: true
	}, {
		id: "title4",
		name: "Title4",
		field: "title4",
		cssClass: "cell-title",
		editor: Slick.Editors.Text,
		validator: requiredFieldValidator,
		sortable: true
	}];

	var columnFilters = {};

	var options = {
		editable: true,
		enableAddRow: true,
		enableCellNavigation: true,
		asyncEditorLoading: true,
		forceFitColumns: false,
		autoEdit: false,
		topPanelHeight: 25,
		frozenColumn: 2,
		frozenRow: 5,
		showHeaderRow: true,
		syncColumnCellResize: false
	};

	var sortcol = "title";
	var sortdir = 1;
	var percentCompleteThreshold = 0;
	var searchString = "";

	function requiredFieldValidator(value) {
		if (value == null || value == undefined || !value.length) return {
			valid: false,
			msg: "This is a required field"
		};
		else
		return {
			valid: true,
			msg: null
		};
	}

	function updateHeaderRow() {
		for (var i = 0; i < columns.length; i++) {
			if (columns[i].id !== "selector") {
				var header = grid.getHeaderRowColumn(columns[i].id);
				$(header).empty();
				$("<input type='text'>")
					.data("columnId", columns[i].id)
					.val(columnFilters[columns[i].id])
					.appendTo(header);
			}
		}
	}

	function myFilter(item) {
		for (var columnId in columnFilters) {
			if (columnId !== undefined && columnFilters[columnId] !== "") {
				var c = grid.getColumns()[grid.getColumnIndex(columnId)];
				if (item[c.field] != columnFilters[columnId]) {
					return false;
				}
			}
		}

		return true;
	}

	function percentCompleteSort(a, b) {
		return a["percentComplete"] - b["percentComplete"];
	}

	function comparer(a, b) {
		var x = a[sortcol],
			y = b[sortcol];
		return (x == y ? 0 : (x > y ? 1 : -1));
	}

	function addItem(newItem, columnDef) {
		var item = {
			"num": data.length,
			"id": "new_" + (Math.round(Math.random() * 10000)),
			"title": "New task",
			"duration": "1 day",
			"percentComplete": 0,
			"start": "01/01/2009",
			"finish": "01/01/2009",
			"effortDriven": false
		};
		$.extend(item, newItem);
		dataView.addItem(item);
	}


	function toggleFilterRow() {
		grid.setTopPanelVisibility(!grid.getOptions().showTopPanel);
	}


	$(".grid-header .ui-icon").addClass("ui-state-default ui-corner-all").mouseover(function(e) {
		$(e.target).addClass("ui-state-hover")
	}).mouseout(function(e) {
		$(e.target).removeClass("ui-state-hover")
	});

	$(function() {
		// prepare the data
		for (var i = 0; i < 50000; i++) {
			var d = (data[i] = {});

			d["id"] = "id_" + i;
			d["num"] = i;
			d["title"] = "Task " + i;
			d["duration"] = "5 days";
			d["percentComplete"] = Math.round(Math.random() * 100);
			d["start"] = "01/01/2009";
			d["finish"] = "01/05/2009";
			d["effortDriven"] = (i % 5 == 0);
			d["title1"] = i;
			d["title2"] = i;
			d["title3"] = i;
			d["title4"] = i;
		}


		dataView = new Slick.Data.DataView();
		grid = new Slick.Grid("#myGrid", dataView, columns, options);
		grid.setSelectionModel(new Slick.RowSelectionModel());

		var pager = new Slick.Controls.Pager(dataView, grid, $("#pager"));
		var columnpicker = new Slick.Controls.ColumnPicker(columns, grid, options);


		// move the filter panel defined in a hidden div into an inline secondary grid header row
		var $secondaryRow = grid.getTopPanel();

		$("#inlineFilterPanelL").appendTo($secondaryRow[0]).show();

		$("#inlineFilterPanelR").appendTo($secondaryRow[1]).show();

		grid.onCellChange.subscribe(function(e, args) {
			dataView.updateItem(args.item.id, args.item);
		});

		grid.onAddNewRow.subscribe(function(e, args) {
			var item = {
				"num": data.length,
				"id": "new_" + (Math.round(Math.random() * 10000)),
				"title": "New task",
				"duration": "1 day",
				"percentComplete": 0,
				"start": "01/01/2009",
				"finish": "01/01/2009",
				"effortDriven": false
			};
			$.extend(item, args.item);
			dataView.addItem(item);
		});

		grid.onKeyDown.subscribe(function(e) {
			// select all rows on ctrl-a
			if (e.which != 65 || !e.ctrlKey) return false;

			var rows = [];

			for (var i = 0; i < dataView.getLength(); i++) {
				rows.push(i);
			}

			grid.setSelectedRows(rows);
			e.preventDefault();
		});

		grid.onMouseEnter.subscribe(function(e) {
			var cell = this.getCellFromEvent(e);

			this.setSelectedRows([cell.row]);
			e.preventDefault();
		});

		grid.onMouseLeave.subscribe(function(e) {
			this.setSelectedRows([]);
			e.preventDefault();
		});

		grid.onSort.subscribe(function(e, args) {
			sortdir = args.sortAsc ? 1 : -1;
			sortcol = args.sortCol.field;

			if ($.browser.msie && $.browser.version <= 8) {
				// using temporary Object.prototype.toString override
				// more limited and does lexicographic sort only by default, but can be much faster

				var percentCompleteValueFn = function() {
					var val = this["percentComplete"];
					if (val < 10) return "00" + val;
					else if (val < 100) return "0" + val;
					else
					return val;
				};

				// use numeric sort of % and lexicographic for everything else
				dataView.fastSort((sortcol == "percentComplete") ? percentCompleteValueFn : sortcol, args.sortAsc);
			} else {
				// using native sort with comparer
				// preferred method but can be very slow in IE with huge datasets
				dataView.sort(comparer, args.sortAsc);
			}
		});

		// wire up model events to drive the grid
		dataView.onRowCountChanged.subscribe(function(e, args) {
			grid.updateRowCount();
			grid.render();
		});

		dataView.onRowsChanged.subscribe(function(e, args) {
			grid.invalidateRows(args.rows);
			grid.render();
		});

		dataView.onPagingInfoChanged.subscribe(function(e, pagingInfo) {
			var isLastPage = pagingInfo.pageSize * (pagingInfo.pageNum + 1) - 1 >= pagingInfo.totalRows;
			var enableAddRow = isLastPage || pagingInfo.pageSize == 0;
			var options = grid.getOptions();

			if (options.enableAddRow != enableAddRow) grid.setOptions({
				enableAddRow: enableAddRow
			});
		});

		$(grid.getHeaderRow()).delegate(":input", "change keyup", function(e) {
			columnFilters[$(this).data("columnId")] = $.trim($(this).val());
			dataView.refresh();
		});


		grid.onColumnsReordered.subscribe(function(e, args) {
			updateHeaderRow();
		});

		grid.onColumnsResized.subscribe(function(e, args) {
			updateHeaderRow();
		});

		var h_runfilters = null;

		// wire up the slider to apply the filter to the model
		// wire up the slider to apply the filter to the model
		$("#pcSlider,#pcSlider2").slider({
			"range": "min",
			"slide": function(event, ui) {
				Slick.GlobalEditorLock.cancelCurrentEdit();

				if (percentCompleteThreshold != ui.value) {
					window.clearTimeout(h_runfilters);
					h_runfilters = window.setTimeout(dataView.refresh, 10);
					percentCompleteThreshold = ui.value;
				}
			}
		});

		// wire up the search textbox to apply the filter to the model
		$("#txtSearch,#txtSearch2").keyup(function(e) {
			Slick.GlobalEditorLock.cancelCurrentEdit();

			// clear on Esc
			if (e.which == 27) this.value = "";

			searchString = this.value;
			dataView.refresh();
		});

		$("#btnSelectRows").click(function() {
			if (!Slick.GlobalEditorLock.commitCurrentEdit()) {
				return;
			}

			var rows = [];

			for (var i = 0; i < 10 && i < dataView.getLength(); i++) {
				rows.push(i);
			}

			grid.setSelectedRows(rows);
		});

		// initialize the model after all the events have been hooked up
		dataView.beginUpdate();
		dataView.setItems(data);
		dataView.setFilter(myFilter);
		dataView.endUpdate();

		// if you don't want the items that are not visible (due to being filtered out
		// or being on a different page) to stay selected, pass 'false' to the second arg
		dataView.syncGridSelection(grid, true);

		updateHeaderRow();

		$("#gridContainer").resizable();

		$('#setFrozenRow').click(function() {
			var val = -1;

			if ($('#frozenRow').val() != '') {
				val = parseInt($('#frozenRow').val());
			}

			grid.setOptions({
				'frozenRow': val
			});

			updateHeaderRow();
		});

		$('#setFrozenColumn').click(function() {
			var val = -1;

			if ($('#frozenColumn').val() != '') {
				val = parseInt($('#frozenColumn').val());
			}

			grid.setOptions({
				'frozenColumn': val
			});

			updateHeaderRow();
		});
	})</script>

	</body>
</html>
